/**
 * 重试管理器 - 实现指数退避重试机制
 * 支持连续验证和失败自动重跑
 */
export class RetryManager {
  private maxRetries: number;
  private baseDelayMs: number;
  private maxDelayMs: number;

  constructor(maxRetries: number = 6, baseDelayMs: number = 2000, maxDelayMs: number = 60000) {
    this.maxRetries = maxRetries;
    this.baseDelayMs = baseDelayMs;
    this.maxDelayMs = maxDelayMs;
  }

  /**
   * 执行带重试的操作
   */
  async executeWithRetry<T>(operation: () => Promise<T>): Promise<T> {
    let lastError: Error | null = null;
    
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        console.log(`执行尝试 ${attempt}/${this.maxRetries}`);
        
        const result = await operation();
        
        if (attempt > 1) {
          console.log(`第${attempt}次尝试成功`);
        }
        
        return result;
      } catch (error) {
        lastError = error as Error;
        console.error(`第${attempt}次尝试失败:`, error);
        
        if (attempt < this.maxRetries) {
          const delay = this.calculateDelay(attempt);
          console.log(`等待 ${delay}ms 后重试...`);
          await this.sleep(delay);
        }
      }
    }
    
    throw new Error(`经过${this.maxRetries}次尝试后仍然失败。最后错误: ${lastError?.message}`);
  }

  /**
   * 计算指数退避延迟时间
   */
  private calculateDelay(attempt: number): number {
    // 指数退避: 2^attempt * baseDelay
    const exponentialDelay = Math.pow(2, attempt - 1) * this.baseDelayMs;
    
    // 添加随机抖动 (±25%)
    const jitter = exponentialDelay * 0.25 * (Math.random() * 2 - 1);
    const delayWithJitter = exponentialDelay + jitter;
    
    // 限制最大延迟时间
    return Math.min(delayWithJitter, this.maxDelayMs);
  }

  /**
   * 睡眠指定毫秒数
   */
  private async sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 执行连续验证（多次成功才算通过）
   */
  async executeConsecutiveVerification<T>(
    operation: () => Promise<T>,
    requiredSuccesses: number = 3,
    resetOnFailure: boolean = true
  ): Promise<T[]> {
    const results: T[] = [];
    let consecutiveSuccesses = 0;
    let totalAttempts = 0;
    const maxTotalAttempts = this.maxRetries * requiredSuccesses;
    
    while (consecutiveSuccesses < requiredSuccesses && totalAttempts < maxTotalAttempts) {
      totalAttempts++;
      
      try {
        console.log(`连续验证: 第${totalAttempts}次尝试 (已连续成功${consecutiveSuccesses}/${requiredSuccesses}次)`);
        
        const result = await operation();
        results.push(result);
        consecutiveSuccesses++;
        
        console.log(`第${totalAttempts}次尝试成功，连续成功次数: ${consecutiveSuccesses}/${requiredSuccesses}`);
        
        // 如果还需要更多成功，在尝试之间等待
        if (consecutiveSuccesses < requiredSuccesses) {
          const delay = this.baseDelayMs;
          console.log(`等待 ${delay}ms 后进行下一次验证...`);
          await this.sleep(delay);
        }
        
      } catch (error) {
        console.error(`第${totalAttempts}次尝试失败:`, error);
        
        if (resetOnFailure) {
          // 失败后重置连续成功计数
          consecutiveSuccesses = 0;
          results.length = 0; // 清空之前的结果
          console.log('失败后重置连续成功计数');
        }
        
        // 计算重试延迟
        const delay = this.calculateDelay(totalAttempts);
        console.log(`等待 ${delay}ms 后重试...`);
        await this.sleep(delay);
      }
    }
    
    if (consecutiveSuccesses < requiredSuccesses) {
      throw new Error(
        `连续验证失败: 需要连续${requiredSuccesses}次成功，但经过${totalAttempts}次尝试后只有${consecutiveSuccesses}次连续成功`
      );
    }
    
    console.log(`连续验证成功: ${requiredSuccesses}次连续成功，总尝试次数: ${totalAttempts}`);
    return results;
  }

  /**
   * 执行带超时的操作
   */
  async executeWithTimeout<T>(
    operation: () => Promise<T>,
    timeoutMs: number = 120000 // 默认2分钟超时
  ): Promise<T> {
    return new Promise<T>(async (resolve, reject) => {
      const timeoutId = setTimeout(() => {
        reject(new Error(`操作超时: ${timeoutMs}ms`));
      }, timeoutMs);
      
      try {
        const result = await operation();
        clearTimeout(timeoutId);
        resolve(result);
      } catch (error) {
        clearTimeout(timeoutId);
        reject(error);
      }
    });
  }

  /**
   * 执行带重试和超时的操作
   */
  async executeWithRetryAndTimeout<T>(
    operation: () => Promise<T>,
    timeoutMs: number = 120000
  ): Promise<T> {
    return this.executeWithTimeout(
      () => this.executeWithRetry(operation),
      timeoutMs
    );
  }

  /**
   * 批量执行操作（并行）
   */
  async executeBatch<T>(
    operations: (() => Promise<T>)[],
    concurrency: number = 3
  ): Promise<T[]> {
    const results: T[] = [];
    const errors: Error[] = [];
    
    // 分批执行
    for (let i = 0; i < operations.length; i += concurrency) {
      const batch = operations.slice(i, i + concurrency);
      
      const batchPromises = batch.map(async (operation, index) => {
        try {
          return await this.executeWithRetry(operation);
        } catch (error) {
          errors.push(new Error(`批次操作${i + index + 1}失败: ${(error as Error).message}`));
          throw error;
        }
      });
      
      try {
        const batchResults = await Promise.all(batchPromises);
        results.push(...batchResults);
      } catch (error) {
        console.error(`批次执行失败:`, error);
        // 继续执行下一批次
      }
    }
    
    if (errors.length > 0) {
      console.warn(`批量执行完成，但有${errors.length}个操作失败`);
    }
    
    return results;
  }

  /**
   * 获取重试统计信息
   */
  getRetryStats(): {
    maxRetries: number;
    baseDelayMs: number;
    maxDelayMs: number;
  } {
    return {
      maxRetries: this.maxRetries,
      baseDelayMs: this.baseDelayMs,
      maxDelayMs: this.maxDelayMs
    };
  }

  /**
   * 设置重试参数
   */
  setRetryParams(maxRetries?: number, baseDelayMs?: number, maxDelayMs?: number): void {
    if (maxRetries !== undefined) this.maxRetries = maxRetries;
    if (baseDelayMs !== undefined) this.baseDelayMs = baseDelayMs;
    if (maxDelayMs !== undefined) this.maxDelayMs = maxDelayMs;
  }
}